package com.zpark.evaluate;

import com.zpark.entity.EvaluateData;
import com.zpark.entity.EvaluateReport;
import com.zpark.entity.HistoryData;
import com.zpark.entity.RiskFactor;

import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Stream;

/**
 * 登录习惯的评估
 * 根据当前需要评估的数据的登录时间，结合历史留存的登录习惯(Map)完成评估
 */
public class TimeslotEvaluate extends Evaluate {
    private int countThreshold;
    //根据这个值判断用户的登录习惯有没有养成
    //如果用户的总登录次数大于了这个值，说明用户的登录习惯已经形成

    public TimeslotEvaluate(int countThreshold) {
        super(RiskFactor.TIMESLOT);
        this.countThreshold = countThreshold;
    }

    @Override
    public void eval(EvaluateData evaluateData, HistoryData historyData, EvaluateReport evaluateReport, EvaluateChain evaluateChain) {

        //1.对登录习惯进行评估
        boolean isRisk=doEval(evaluateData.getEvaluateTime(),historyData.getHistoryLoginTimeSlot());
        evaluateReport.signReport(RiskFactor.TIMESLOT,isRisk);
        //2.让评估继续
        evaluateChain.doChain(evaluateData, historyData, evaluateReport);
    }

    private boolean doEval(long evaluateTime, Map<String, Map<String, Integer>> historyLoginTimeSlot) {

        //1.如果是第一次登录，没有风险；return false;
        if(historyLoginTimeSlot==null || historyLoginTimeSlot.size()==0){
            return false;
        }

        //2.如果登录总次数没有到达规定的值(this.countThreshold),用户的登录习惯还没有形成，没有风险
        //通过historyLoginTimeSlot计算总登录次数
        /*
        //通过流计算登录次数
        Collection<Map<String, Integer>> values = historyLoginTimeSlot.values();//获取到map中的所有value（每一个value是一个Map）
        Stream<Integer> integerStream = values.stream().map(e -> e.values().stream().reduce((v1, v2) -> v1 + v2).get());//一天的总登录次数
        Integer totalCount = integerStream.reduce((v1, v2) -> v1 + v2).get();//总登录次数
        */

        //用循环计算登录次数
        int totalCount=0;
        Collection<Map<String, Integer>> values = historyLoginTimeSlot.values();//获取到所有的value
        for (Map<String, Integer> map : values) {
            Collection<Integer> values1 = map.values();//
            for (Integer integer : values1) {
                totalCount+=integer;
            }
        }

        if(totalCount<countThreshold){
            //登录习惯还没有养成
            return false;
        }

        //登录习惯已经形成啦，需要判断，当前的登录是否符合用户的登录习惯
        //1.如果要评估的数据的星期，在map中不存在；不符合用户的登录习惯，认定该评估项有风险
        //2.星期在map中存在，根据星期，从map中读取一个值（map2）;如果要评估的数据的小时，在map2中不存在,不符合用户的登录习惯
        //3.小时在map2中存在

        //运用工具类计算出用户登录的时间为星期几
        String[] WEEKS={"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};//定义一个数组

        Date date = new Date(evaluateTime);//指定的时间
//        int date1 = date.getDate();//几号
        int day = date.getDay();//星期，0表示周日，1表示周一...6表示周六
        String week = WEEKS[day];//星期
        int hours = date.getHours();//小时

//        Calendar calendar = Calendar.getInstance();//创建一个Calendar对象；日历对象;获取到的就是当前时间的日历对象
//        calendar.setTimeInMillis(evaluateTime);
//        String dayOfWeek = WEEKS[calendar.get(Calendar.DAY_OF_WEEK) - 1];
//        //计算出用户登录的时间小时数 转换为二位数字  01 02 ... 24
//        DecimalFormat decimalFormat=new DecimalFormat("00");
//        String hourOfDay=  decimalFormat.format(calendar.get(Calendar.HOUR_OF_DAY));

        if(!historyLoginTimeSlot.containsKey(week)){//评估的数据的星期，在map中不存在
            //不符合用户的登录习惯
            return true;//有风险
        }

        Map<String, Integer> map2 = historyLoginTimeSlot.get(week);
        if(!map2.containsKey(hours)){//要评估的数据的小时，在map2中不存在
            //不符合用户的登录习惯
            return true;//有风险

        }
        //获取当前hours这个时间点的登录次数
        Integer currentHoursCount = map2.get(hours);
        //从map2中获取到所有小时的登录次数，按照升序排列，取三分之二位置处作为判断的阈值
        List<Integer> values1 = (List<Integer>) map2.values();//??????
        Collections.sort(values1);
        Integer threshold = values1.get(values1.size() * 2 / 3);//取一个可以判断的阈值：取排序之后的数据的三分之二位置作为判断的阈值

        //如果当前时间点的登录次数大于判断的阈值，就认定没有风险
        return !(currentHoursCount>threshold);
    }
}
